diff options
Diffstat (limited to 'app/[lng]/partners/(partners)/document-list-only/[contractId]/page.tsx')
| -rw-r--r-- | app/[lng]/partners/(partners)/document-list-only/[contractId]/page.tsx | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/app/[lng]/partners/(partners)/document-list-only/[contractId]/page.tsx b/app/[lng]/partners/(partners)/document-list-only/[contractId]/page.tsx new file mode 100644 index 00000000..e3cda9b4 --- /dev/null +++ b/app/[lng]/partners/(partners)/document-list-only/[contractId]/page.tsx @@ -0,0 +1,175 @@ +// document-stages-management-page.tsx +import { Suspense } from "react" +import { Separator } from "@/components/ui/separator" +import { Skeleton } from "@/components/ui/skeleton" +import { type SearchParams } from "@/types/table" +import { getValidFilters } from "@/lib/data-table" +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { Progress } from "@/components/ui/progress" +import { + TrendingUp, + AlertTriangle, + Clock, + Target, + FileText, + Settings, + Download +} from "lucide-react" +import { Button } from "@/components/ui/button" +import { DocumentStagesTable } from "@/lib/vendor-document-list/plant/document-stages-table" +import { documentStageSearchParamsCache } from "@/lib/vendor-document-list/plant/document-stage-validations" +import { getDocumentProgressStats, getDocumentStagesOnly } from "@/lib/vendor-document-list/plant/document-stages-service" + +interface DocumentStagesManagementPageProps { + params: { + contractId: string + } + searchParams: Promise<SearchParams> +} + + +// 전체 진행률 카드 컴포넌트 +async function ProgressCard({ contractId }: { contractId: number }) { + const stats = await getDocumentProgressStats(contractId) + + return ( + <Card> + <CardHeader> + <div className="flex items-center justify-between"> + <CardTitle className="text-lg">전체 진행률</CardTitle> + <div className="flex items-center gap-2"> + </div> + </div> + </CardHeader> + <CardContent> + <div className="space-y-4"> + <div className="flex justify-between text-sm"> + <span>평균 진행률</span> + <span className="font-medium">{stats.avgProgress}%</span> + </div> + <Progress value={stats.avgProgress} className="w-full" /> + + <div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm"> + <div className="text-center p-2 bg-gray-50 rounded"> + <div className="font-medium text-lg text-gray-900">{stats.totalDocuments}</div> + <div className="text-gray-600">전체</div> + </div> + <div className="text-center p-2 bg-green-50 rounded"> + <div className="font-medium text-lg text-green-600">{stats.completedDocuments}</div> + <div className="text-green-600">완료</div> + </div> + <div className="text-center p-2 bg-blue-50 rounded"> + <div className="font-medium text-lg text-blue-600">{stats.inProgressDocuments}</div> + <div className="text-blue-600">진행중</div> + </div> + <div className="text-center p-2 bg-red-50 rounded"> + <div className="font-medium text-lg text-red-600">{stats.overdueDocuments}</div> + <div className="text-red-600">지연</div> + </div> + </div> + </div> + </CardContent> + </Card> + ) +} + +// 문서 테이블 래퍼 컴포넌트 +async function DocumentTableWrapper({ + contractId, + searchParams, + projectType +}: { + contractId: number + searchParams: any + projectType: "ship" | "plant" +}) { + const search = documentStageSearchParamsCache.parse(searchParams) + const validFilters = getValidFilters(search.filters) + + const documentsPromise = getDocumentStagesOnly({ + ...search, + filters: validFilters, + }, contractId) + + return ( + <DocumentStagesTable + promises={Promise.all([documentsPromise])} + contractId={contractId} + projectType={projectType} + initialDrawingKind={search.drawingKind} + /> + ) +} + + + +function TableLoadingSkeleton() { + return ( + <div className="space-y-4"> + <div className="flex items-center justify-between"> + <Skeleton className="h-6 w-32" /> + <div className="flex items-center gap-2"> + <Skeleton className="h-8 w-20" /> + <Skeleton className="h-8 w-24" /> + </div> + </div> + <div className="rounded-md border"> + <div className="p-4"> + <div className="space-y-3"> + {Array.from({ length: 5 }).map((_, i) => ( + <div key={i} className="flex items-center space-x-4"> + <Skeleton className="h-4 w-4" /> + <Skeleton className="h-4 w-24" /> + <Skeleton className="h-4 w-48" /> + <Skeleton className="h-4 w-20" /> + <Skeleton className="h-4 w-16" /> + <Skeleton className="h-4 w-12" /> + </div> + ))} + </div> + </div> + </div> + </div> + ) +} + +// 메인 페이지 컴포넌트 +export default async function DocumentStagesManagementPage({ + params, + searchParams +}: DocumentStagesManagementPageProps) { + const resolvedParams = await params + const contractId = Number(resolvedParams.contractId) + const resolvedSearchParams = await searchParams + + // 프로젝트 타입 결정 (실제로는 계약 정보에서 가져와야 함) + const projectType = resolvedSearchParams.projectType === "plant" ? "plant" : "ship" + + if (isNaN(contractId)) { + throw new Error("유효하지 않은 계약 ID입니다") + } + + return ( + <div className=" mx-auto"> + + {/* 문서 테이블 */} + {/* <div className="space-y-4"> */} + {/* <div className="flex items-center justify-between"> + <h2 className="text-xl font-semibold">문서 목록</h2> + <div className="text-sm text-muted-foreground"> + 스테이지 상태별로 문서를 관리하고 진행 상황을 추적할 수 있습니다 + </div> + </div> */} + + <Suspense fallback={<TableLoadingSkeleton />}> + <DocumentTableWrapper + contractId={contractId} + searchParams={resolvedSearchParams} + projectType={projectType} + /> + </Suspense> + {/* </div> */} + + </div> + ) +}
\ No newline at end of file |
